package com.gitee.wsl.doc.sample.opml.bean

import kotlinx.serialization.Serializable

/**
 *
 *
 * An `<outline>` is an XML element containing at least one required attribute, text, and zero or more additional
 * attributes. An `<outline>` may contain zero or more `<outline>` sub-elements. No attribute may be
 * repeated within the same `<outline>` element.
 *
 *
 *
 * Instances are unmodifiable and threadsafe.
 *
 */
@Serializable
data class Outline(
    /**
     * @return unmodifiable [Map] with all attributes of this [Outline]
     */
    val attributes: Map<String, String>,
    val subElements: List<Outline>
)  {

    /**
     * @param attributes
     * a [Map], can not be `null`, can not contain `null` or blank [String] as key
     * @param subElements
     * a [List], can not be `null`
     * @throws IllegalArgumentException
     * if either argument `null` or if `attributes` contains a blank key
     */
//    init {
//        requireNotNull(attributes) { "attributes can not be null" }
//        requireNotNull(subElements) { "subElements can not be null" }
//        val map: MutableMap<String, String> = HashMap()
//        for ((key, value) in attributes) {
//            require(!ValidityCheck.isTextBlank(key)) { "attributes map contains a null or blank key" }
//            map[key] = value
//        }
//        this.attributes = Collections.unmodifiableMap(map)
//        this.subElements = Collections.unmodifiableList(ArrayList(subElements))
//    }

    /**
     * Convenience method. Equivalent to:
     *
     * <pre>
     * `getAttributes().get(key);`
    </pre> *
     *
     * @param key
     * a [String], can not be null
     * @return the value of that attribute, or `null` if not available
     */
    fun getAttribute(key: String): String? {
        //requireNotNull(key) { "key can not be null" }
        return attributes[key]
    }

    val text: String?
        /**
         * Convenience method. Equivalent to:
         *
         * <pre>
         * `getAttributes().get("text");`
        </pre> *
         *
         * As per the specification of OPML 2.0, the text attribute is required. However, it is not in the version 1.0 spec.
         *
         * @return the value of attribute text, or `null` if not available
         */
        get() = attributes["text"]

    /**
     * @param index
     * index of the element to return
     * @return [Outline] at the given index, or `null` if there is no element at that index
     */
    fun getSubElement(index: Int): Outline? {
        if (index < subElements.size) {
            return subElements[index]
        }
        return null
    }


    override fun toString(): String {
        val sb = StringBuilder("Outline [attributes=").append(attributes).append(", subElements=")
        for (outline in subElements) {
            sb.append(System.lineSeparator()).append("\t").append(outline)
        }
        return sb.append("]").toString()
    }

}